package com.gitee.chenyaohua.oa.util.secret;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

import com.gitee.chenyaohua.oa.util.io.IOUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.crypto.codec.Hex;

@Slf4j
public class SecretUtils {

	private static final String ENCRYPTION_TYPE_DESEDE = "DESede";

	private static String DESEDE_KEY;

	static {
		ClassPathResource resour = new ClassPathResource("secret/desede/desedeKey");
		try {
			InputStream inputStream1 = resour.getInputStream();
			DESEDE_KEY = IOUtil.readFull(inputStream1);
		} catch (IOException e) {
			log.error("敏感数据加密初始化公钥失败",e);
		}
	}

	/**
	 * 生成密匙对
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
		KeyPairGenerator instance = KeyPairGenerator.getInstance("RSA");
		instance.initialize(1024);
		return instance.generateKeyPair();
	}
	
	
	/**
	 * 加密
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	public static String encode(String publiceStr,String payload) throws Exception {
		//公钥
		byte[] decode = Base64.getDecoder().decode(publiceStr.getBytes(StandardCharsets.UTF_8));
		X509EncodedKeySpec x509Enc = new X509EncodedKeySpec(decode);
		KeyFactory instance = KeyFactory.getInstance("RSA");
		PublicKey generatePublic = instance.generatePublic(x509Enc);
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, generatePublic);
		byte[] doFinal = cipher.doFinal(payload.getBytes(StandardCharsets.UTF_8));
		return Base64.getEncoder().encodeToString(doFinal);
	}
	
	
	
	/**
	 * RSA/ECB/NoPadding
	 * RSA/ECB/PKCS1Padding
	 *
	 * 解密
	 * @return
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 * @throws NoSuchPaddingException 
	 * @throws InvalidKeyException 
	 * @throws BadPaddingException 
	 * @throws IllegalBlockSizeException 
	 */
	public static String decode(String privateStr,String payload) throws Exception {
			//私钥
			byte[] decode = Base64.getDecoder().decode(privateStr.getBytes(StandardCharsets.UTF_8));
			PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(decode);
			KeyFactory instance = KeyFactory.getInstance("RSA");
			PrivateKey generatePrivate = instance.generatePrivate(pkcs8);

			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, generatePrivate);
			//加密字符串base64解密解密
			byte[] bytes = payload.getBytes(StandardCharsets.UTF_8);
			byte[] decode2 = Base64.getDecoder().decode(bytes);
			//加密字符串rsa解密
			byte[] doFinal = cipher.doFinal(decode2);
		return new String(doFinal, StandardCharsets.UTF_8);
	}

	
	/**
	 * 签名
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	public static String sign(String privateStr,String payload) throws Exception {
		//私钥
		byte[] decode = Base64.getDecoder().decode(privateStr.getBytes(StandardCharsets.UTF_8));
		PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(decode);
		KeyFactory instance = KeyFactory.getInstance("RSA");
		PrivateKey generatePrivate = instance.generatePrivate(pkcs8);
		Signature signature = Signature.getInstance("MD5withRSA");
		signature.initSign(generatePrivate);
		signature.update(payload.getBytes(StandardCharsets.UTF_8));
//		Base64.getEncoder().encodeToString(signature.sign())
		return new String(Hex.encode(signature.sign()));
	}
	
	
	/**
	 * 签名
	 * @return
	 * @throws NoSuchAlgorithmException 
	 */
	public static boolean verifySign(String publiceKey,String signStr,String payload) throws Exception {
		//公钥
		byte[] decode = Base64.getDecoder().decode(publiceKey.getBytes());
		X509EncodedKeySpec x509 = new X509EncodedKeySpec(decode);
		KeyFactory instance = KeyFactory.getInstance("RSA");
		PublicKey generatePublic = instance.generatePublic(x509);
		Signature sign = Signature.getInstance("MD5withRSA");
		sign.initVerify(generatePublic);
		sign.update(payload.getBytes(StandardCharsets.UTF_8));
//		sign.verify(Base64.getDecoder().decode(signStr.getBytes("UTF-8")))
		return sign.verify(Hex.decode(signStr));
	}
	
	
	public static String md5(String text) throws Exception {
		MessageDigest instance = MessageDigest.getInstance("MD5");
		instance.update(text.getBytes());
		byte[] digest = instance.digest();
		return new String(Hex.encode(digest));
	}



	public static String generateDesedeKey() throws NoSuchAlgorithmException {
		KeyGenerator instance = KeyGenerator.getInstance(ENCRYPTION_TYPE_DESEDE);
		instance.init(168);
		byte[] encoded = instance.generateKey().getEncoded();
		return Base64.getEncoder().encodeToString(encoded);
	}

	public static String des3Decode(String text) throws Exception {
		Cipher instance = Cipher.getInstance(ENCRYPTION_TYPE_DESEDE);
		byte[] decode = Base64.getDecoder().decode(DESEDE_KEY);
		byte[] byText = Base64.getDecoder().decode(text);
		instance.init(Cipher.DECRYPT_MODE,new SecretKeySpec(decode,ENCRYPTION_TYPE_DESEDE));
		byte[] bytes = instance.doFinal(byText);
		return new String(bytes);
	}

	public static String des3Encode(String text) throws Exception {
		Cipher instance = Cipher.getInstance(ENCRYPTION_TYPE_DESEDE);
		byte[] decode = Base64.getDecoder().decode(DESEDE_KEY);
		instance.init(Cipher.ENCRYPT_MODE,new SecretKeySpec(decode,ENCRYPTION_TYPE_DESEDE));
		byte[] bytes = instance.doFinal(text.getBytes(StandardCharsets.UTF_8));
		return Base64.getEncoder().encodeToString(bytes);
	}

}
